package com.cml.dm.admin.service.impl;

import cn.hutool.core.io.IoUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.cml.dm.admin.entity.DmExeLogger;
import com.cml.dm.admin.entity.DmMetadata;
import com.cml.dm.admin.mapper.DmExeLoggerMapper;
import com.cml.dm.admin.mapper.DynamicSqlMapper;
import com.cml.dm.admin.service.EncryptionFactory;
import com.cml.dm.admin.service.FileCompressFactory;
import com.cml.dm.admin.service.handler.BackupTaskHandler;
import com.cml.dm.admin.service.handler.DelDataTaskHandler;
import com.cml.dm.admin.service.handler.RecoveryTaskHandler;
import com.cml.dm.admin.service.handler.TaskHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.support.JdbcUtils;
import org.springframework.stereotype.Service;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.nio.ByteBuffer;
import java.util.*;

@Service
public class RecoveryTaskExecutorService extends AbstractTaskExecutorService{

    private static final Logger logger = LoggerFactory.getLogger(RecoveryTaskExecutorService.class);

    @Autowired
    private FileCompressFactory fileCompressFactory;
    @Autowired
    private EncryptionFactory encryptionFactory;
    @Autowired
    private DynamicSqlMapper dynamicSqlMapper;
    @Autowired
    private DmExeLoggerMapper dmExeLoggerMapper;

    @Override
    public void doTask(DmMetadata dmMetadata, DmExeLogger dmExeLogger, Object extParameter) {
        //读出整个文件json，变解析出存储的原始数据
        Map<String, JSONObject> dataMap = this.resolvingData(dmExeLogger);

        //恢复的逻辑：先备份现有数据，再删除多余数据，再进行恢复


        //逆向进行数据恢复
        //备份
        TaskHandler backupTaskHandler = new BackupTaskHandler();
        //数据删除
        TaskHandler delDataTaskHandler = new DelDataTaskHandler();
        delDataTaskHandler.setExeLogger(dmExeLogger);
        //数据恢复
        TaskHandler recoveryTaskHandler = new RecoveryTaskHandler();
        recoveryTaskHandler.setExeLogger(dmExeLogger);

        backupTaskHandler.setNexTaskHandler(delDataTaskHandler);
        delDataTaskHandler.setNexTaskHandler(recoveryTaskHandler);

        //=== 先执行的备份，需要重新新建立一个exeLogger
        DmExeLogger backupExeLogger = new DmExeLogger();
        BeanUtils.copyProperties(dmExeLogger, backupExeLogger);
        backupExeLogger.setExeTime(new Date());
        backupExeLogger.setExeType(dmExeLogger.backup());
        backupExeLogger.setBackupPath(null);
        backupExeLogger.setExeStatus(0);
        backupExeLogger.setId(null);
        dmExeLoggerMapper.insert(backupExeLogger);
        backupTaskHandler.setExeLogger(backupExeLogger);
        //=== 先执行的备份，需要重新新建立一个exeLogger

        backupTaskHandler.doExecute(dmMetadata,backupTaskHandler.getExeLogger(),dataMap);
    }

    private Map<String, JSONObject> resolvingData(DmExeLogger dmExeLogger){
        String backPath = dmExeLogger.getBackupPath();
        FileInputStream fis = null;
        ByteArrayOutputStream baos = null;
        Map<String, JSONObject> dataMap = new HashMap<>();
        try {
            //是zip文件文件，需要进行解压
            List<String> paths = fileCompressFactory.uncompress(backPath);
            String ucFilePath = paths.get(0);
            File file = new File(ucFilePath);
            fis = new FileInputStream(file);
            byte[] bytes = new byte[16];
            int len = 0;
            baos = new ByteArrayOutputStream();
            while (-1 != (len = fis.read(bytes))){
                baos.write(bytes);
            }
            baos.flush();
            byte[] eb = encryptionFactory.decode(baos.toByteArray());
            String dJson = new String(eb,"UTF-8");
            JSONObject jsonObject = JSONObject.parseObject(dJson);
            JSONArray datas = jsonObject.getJSONArray("datas");
            for(int i = 0; i < datas.size(); i++){
                JSONObject nodeJson = datas.getJSONObject(i);
                for(String key : nodeJson.keySet()){
                    dataMap.put(key,nodeJson.getJSONObject(key));
                }
            }
        }catch (Exception e){
            logger.error("解析备份数据失败：",e);
            throw new RuntimeException("解析备份数据失败");
        }finally {
            IoUtil.close(baos);
            IoUtil.close(fis);
        }
        return dataMap;
    }
}
